﻿using System;

namespace V8.Net
{
    /// <summary>
    /// 确定脚本可访问性的标志。
    /// </summary>
    [Flags]
    public enum ScriptMemberSecurity
    {
        /// <summary>
        /// 在内部使用,以防止访问脚本成员
        /// </summary>
        NoAcccess = -1, //(注意:映射到'V8PropertyAttributes.Undefined'[也是-1];未定义的成员将被忽略)

        /// <summary>
        /// 如果设置了此标志,则可以读取和/或写入属性
        /// <para>注意:这是默认行为,不需要显式设置</para>
        /// </summary>
        ReadWrite = V8PropertyAttributes.None,

        /// <summary>如果设置了此标志,则只能读取属性(优先于'ReadWrite')</summary>
        ReadOnly = V8PropertyAttributes.ReadOnly,

        /// <summary>如果设置了此标志,则该属性对枚举(而不是对访问)隐藏</summary>
        Hidden = V8PropertyAttributes.DontEnum,

        /// <summary>如果设置了此标志,则无法删除该属性(从脚本内)</summary>
        Permanent = V8PropertyAttributes.DontDelete,

        /// <summary>如果设置了此标志,则不能删除或覆盖属性(从脚本内;这等同于设置两个'Permanent|ReadOnly'标志)</summary>
        Locked = V8PropertyAttributes.Locked
    };

    // ========================================================================================================================

    /// <summary>
    /// 默认情况下，出于安全原因，脚本无法访问公共类成员（除非使用了'ScriptObject'属性）。
    /// 此属性允许控制如何将类成员暴露给脚本环境。
    /// </summary>
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class ScriptMember : Attribute
    {
        // --------------------------------------------------------------------------------------------------------------------

        public string InScriptName { get; private set; }

        public ScriptMemberSecurity Security { get { return _Security; } private set { _Security = value; } }
        ScriptMemberSecurity _Security = ScriptMemberSecurity.ReadWrite;

        // --------------------------------------------------------------------------------------------------------------------

        /// <summary>
        /// 允许控制该类成员如何暴露于脚本环境。
        /// </summary>
        /// <param name="inScriptName">公开给该成员的脚本环境的类型名称（默认为null / empty，表示按原样使用成员名称）。</param>
        /// <param name="security">该成员的脚本访问安全性。</param>
        public ScriptMember(string inScriptName = null, ScriptMemberSecurity security = ScriptMemberSecurity.ReadWrite)
        {
            InScriptName = inScriptName;
            Security = security;
        }

        /// <summary>
        /// 允许控制该类成员如何暴露于脚本环境。
        /// </summary>
        /// <param name="security">该成员的脚本访问安全性。</param>
        public ScriptMember(ScriptMemberSecurity security)
        {
            Security = security;
        }

        // --------------------------------------------------------------------------------------------------------------------
    }

    /// <summary>
    /// 此属性允许一次为类的所有公共成员指定默认成员访问权限。
    /// 如果仅使用属性名称，则在可能的情况下，每个成员的安全性默认为“无”（V8默认）。
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public class ScriptObject : Attribute
    {
        // --------------------------------------------------------------------------------------------------------------------

        public string TypeName { get; private set; }

        public ScriptMemberSecurity Security { get { return _Security; } private set { _Security = value; } }
        ScriptMemberSecurity _Security = ScriptMemberSecurity.ReadWrite;

        // --------------------------------------------------------------------------------------------------------------------

        /// <summary>
        /// 允许一次为此类的所有公共成员指定默认成员访问权限。
        /// </summary>
        /// <param name="typeName">将类暴露给脚本环境时要使用的函数名（默认为null / empty，表示按原样使用类名）。</param>
        /// <param name="security">所有公共类成员的全局默认访问权限（默认为读/写）。</param>
        public ScriptObject(string typeName = null, ScriptMemberSecurity security = ScriptMemberSecurity.ReadWrite)
        {
            TypeName = typeName;
            Security = security;
        }

        /// <summary>
        /// 允许一次为类的所有公共成员指定默认成员访问权限。
        /// </summary>
        /// <param name="security">所有公共类成员的全局默认访问权限。</param>
        public ScriptObject(ScriptMemberSecurity security)
        {
            Security = security;
        }

        // --------------------------------------------------------------------------------------------------------------------
    }

    // ========================================================================================================================

    //[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    [Obsolete("改用ScriptMemberAttribute和'NoAccess'。")]
    public class NoScriptAccess { }

    // ========================================================================================================================
}
